import os
import openai
import time
import json
import time
import re
from config import *

#这里需要使用在智增增上注册的账号中自己的API_SECRET_KEY
API_SECRET_KEY = openai_api
BASE_URL = "https://api.zhizengzeng.com/v1/"

#音色列表
voice_list = [
    {"老年人": {"老年奶奶":'ICL_zh_female_heainainai_tob', "婆婆":'zh_female_popo_mars_bigtts'}},
    {"40-50岁": {"邻居阿姨":'ICL_zh_female_linjuayi_tob'}},
    {"30-40岁": {"知识渊博的中年男性":'zh_male_yuanboxiaoshu_moon_bigtts', "湾区大叔":'zh_female_wanqudashu_moon_bigtts', "严肃的英国中年男性":'en_male_smith_mars_bigtts',
                 "成熟稳重的中年英国男性":'en_male_adam_mars_bigtts', "优雅绅士的中年英国男性":'en_male_dryw_mars_bigtts', "Sarah":'en_female_sarah_mars_bigtts',
                 "霸气的武则天":'zh_female_wuzetian_mars_bigtts', "威严的中年古代帝王":'zh_male_silang_mars_bigtts',"严肃的美国中年男性":'zh_male_wennuanahu_moon_bigtts'}},
    {"20-30岁": {"温暖阿虎":'zh_male_wennuanahu_moon_bigtts', "爽快思思":'zh_female_shuangkuaisisi_moon_bigtts', "京腔侃爷":'zh_male_jingqiangkanye_moon_bigtts',
                 "湾湾小何":'zh_female_wanwanxiaohe_moon_bigtts', "呆萌川妹":'zh_female_daimengchuanmei_moon_bigtts',"浩宇小哥":'zh_male_haoyuxiaoge_moon_bigtts',
                 "北京小爷":'zh_male_beijingxiaoye_moon_bigtts', "广西远舟":'zh_male_guangxiyuanzhou_moon_bigtts', "妹坨洁儿":'zh_female_meituojieer_moon_bigtts',
                 "豫州子轩":'zh_male_yuzhouzixuan_moon_bigtts', "Skye":'zh_female_shuangkuaisisi_moon_bigtts', "Harmony":'zh_male_jingqiangkanye_moon_bigtts',
                 "Brayan":'zh_male_shaonianzixin_moon_bigtts', "Morgan":'zh_male_jieshuonansheng_mars_bigtts',"Hope":'zh_female_jitangmeimei_mars_bigtts',
                 "Candy":'zh_female_tiexinnvsheng_mars_bigtts'}},
    {"10-20岁": {"少年梓辛":'zh_male_shaonianzixin_moon_bigtts', "邻家女孩":'zh_female_linjianvhai_moon_bigtts', "活泼女孩":'ICL_zh_female_huoponvhai_tob',
                 "萌丫头":'zh_female_mengyatou_mars_bigtts', "Cutey":'zh_female_mengyatou_mars_bigtts'}},
    {"10岁以下小孩": {"天才童声":'zh_male_tiancaitongsheng_mars_bigtts', "奶气萌娃":'zh_male_naiqimengwa_mars_bigtts', "病弱少女":'ICL_zh_female_bingruoshaonv_tob',
                    "樱桃丸子": 'zh_female_yingtaowanzi_mars_bigtts'}},
    {"旁白解说": {"东方浩然":'zh_male_dongfanghaoran_moon_bigtts', "悬疑解说":'zh_male_changtianyi_mars_bigtts', "少儿故事":'zh_female_shaoergushi_mars_bigtts',
                "磁性解说男声":'zh_male_jieshuonansheng_mars_bigtts', "解说小明":'zh_male_jieshuoxiaoming_moon_bigtts', "开朗姐姐":'zh_female_kailangjiejie_moon_bigtts',
                "甜美悦悦":'zh_female_tianmeiyueyue_moon_bigtts', "知性女声":'zh_female_zhixingnvsheng_mars_bigtts', "心灵鸡汤":'zh_female_xinlingjitang_moon_bigtts',
                "广告解说":'zh_male_chunhui_mars_bigtts', "儒雅青年":'zh_male_ruyaqingnian_mars_bigtts', "擎苍":'zh_male_qingcang_mars_bigtts',
                "霸气青叔":'zh_male_baqiqingshu_mars_bigtts', "鸡汤妹妹":'zh_female_jitangmeimei_mars_bigtts'}},
    {"智能系统": {"灿灿/Shiny":'zh_female_cancan_mars_bigtts', "甜美小源":'zh_female_tianmeixiaoyuan_moon_bigtts'}},
    {"英语听力播音员": {"Anna":'en_female_anna_mars_bigtts'}}
]

# input_file 对输入的文本进行处理，去掉多余的空行，处理后的文本存放在new_text文件夹中
def deal_files(read_path, write_path):
    """
    read_path:要读取的文本在的文件夹路径
    write_path:存放处理后文件的文件夹路径
    对原文文本进行一个处理，去掉文本中的空行
    """
    for filename in os.listdir(read_path):
        if filename.endswith('.txt'):
            old_path = os.path.join(read_path, filename)
            new_path = os.path.join(write_path, filename)

            #读取原文
            with open(old_path, 'r', encoding='utf-8', errors='ignore') as old_file:
                lines = old_file.readlines()

            #将处理后内容写入新的txt文件中
            with open(new_path, 'w', encoding='utf-8') as new_file:
                for line in lines:
                    if line.strip():
                        new_file.write(line)

# chat 创建一个和gpt-4o之间的对话，根据提示词使大模型按照规定的json格式输出
def chat_completions(text_content, voice_list):
    openai.api_key = API_SECRET_KEY
    openai.api_base = BASE_URL

    #添加环境音提取的提示词
    prompt1 = f"""
              请根据文本的内容，按照从前往后的顺序逐行进行分析，请不要遗漏文本内容，对每一行的文本进行两次划分，第一次判断改行文本是人声类别中的旁白还是角色对话，第二次判断是否需要按顺序在后面添加一个环境声的划分。并将结果严格按照给定的JSON格式进行输出。
              对文本进行划分的方式：
              逐行进行判断。如果当前一整行的文本中不存在对话，也就是没有中文的“”或者【】存在，表明当前内容属于人声类别中的旁白，即"info"中的"speaker"为旁白，其中"voice_type"的内容是从音色列表中的"旁白解说"对应部分中选择合适的音色，"content"的内容就是整行文本的内容。
              如果当前一整行的文本存在对话，也就是有中文的“”或者【】存在，表明当前内容属于人声类别中的角色对话，可以根据上下文寻找"speaker"对应的角色，"content"的内容就是“”或【】包裹住的内容。
              之后对当前行的文本进行第二次判断。
              如果当前行第一次被分为人声类别中的旁白，则判断其中是否存在可以制造声音的动词，如果不存在，则不用进行后面的步骤，可以直接处理下一行文本内容；如果存在，标记动词，按照顺序在后面添加一个新的划分，"type"为"环境声"，"info"的值为完整一个英文的句子，句子内容为描述动词最可能产生的声音。
              如果当前行第一次被分为人声类别中的角色对话，则对位于在“”或【】外面的文本内容进行判断，看是否存在除了表述说话含义以外的可以制造声音的动词，如果不存在，则不用进行后面的步骤，可以直接处理下一行文本内容；如果存在，标记该动词，按照顺序在后面添加一个新的划分，"type"为"环境声"，"info"的值为完整一个英文的句子，句子内容为描述当前的"speaker"对应的角色通过该动词最可能发出的声音。
              对文本逐行划分的示例如下：
              一整行文本示例：而且仍然是卫老婆子领着，显出慈悲模样，絮絮的对四婶说：“……这实在是叫作‘天有不测风云’，她的男人是坚实人，谁知道年纪轻轻，就会断送在伤寒上?本来已经好了的，吃了一碗冷饭，复发了。幸亏有儿子;她又能做，打柴摘茶养蚕都来得，本来还可以守着，谁知道那孩子又会给狼衔去的呢?春天快完了，村上倒反来了狼，谁料到?现在她只剩了一个光身了。大伯来收屋，又赶她。她真是走投无路了，只好来求老主人。好在她现在已经再没有什么牵挂，太太家里又凑巧要换人，所以我就领她来。——我想，熟门熟路，比生手实在好得多……。”。
              第一次划分：当前一整行文本中存在对话，即存在中文的“”或【】存在，属于人声类别中的任务对话。其中"type"为"人声","speaker"根据上下文搜索是"卫老婆子"，"content"的值就是“”或【】包裹住的部分。"voice_type"根据"speaker"和"content"判断，应该从音色列表中选择"zh_female_popo_mars_bigtts"。
              第二次划分：当前一整行行文本中不存在可以制造声音的动词，因此不需要在后面按顺序添加"type"为"环境声"的划分。
              一整行文本示例：“我真傻，真的，”祥林嫂抬起她没有神采的眼睛来，接着说。“我单知道下雪的时候野兽在山坳里没有食吃，会到村里来;我不知道春天也会有。我一清早起来就开了门，拿小篮盛了一篮豆，叫我们的阿毛坐在门槛上剥豆去。他是很听话的，我的话句句听;他出去了。我就在屋后劈柴，掏米，米下了锅，要蒸豆。我叫阿毛，没有应，出去口看，只见豆撒得一地，没有我们的阿毛了。他是不到别家去玩的;各处去一问，果然没有。我急了，央人出去寻。直到下半天，寻来寻去寻到山坳里，看见刺柴上桂着一只他的小鞋。大家都说，糟了，怕是遭了狼了。再进去;他果然躺在草窠里，肚里的五脏已经都给吃空了，手上还紧紧的捏着那只小篮呢。……”她接着但是呜咽，说不出成句的话来。
              第一次划分：当前一整行文本中存在对话，即存在中文的“”或【】存在，属于人声类别中的任务对话。其中"type"为"人声","speaker"根据上下文搜索是"祥林嫂"。"content"的值就是“”或【】包裹住的部分。"voice_type"根据"speaker"和"content"判断，应该从音色列表中选择"ICL_zh_female_linjuayi_tob"。
              第二次划分：在当前的一整行文本中，位于“”或【】外部的文本，存在除了表述说话动作之外的可以制造声音的动词，“呜咽”，因此需要在后面按顺序添加"type"为"环境声"的划分，而"info"的值就是使用英文描述的"speaker"根据动词“呜咽”可能发出的声音，即"a middle-aged woman was sobbing"。
              结果使用JSON的格式进行回答。
              JSON格式应包含两个主要部分："type"和 "info"。
              对于两次划分的结果，如果是"人声",要求"info"中包含"speaker","style","voice_type","content"。如果是"环境声",要求"info"中的内容是英文表述的。
              具体形式如下所示：
             -序号(按先后顺序排列)
              -type:"人声"
              -info(详细信息):
                -speaker:人物角色或旁白
                -style:风格
                -voice_type:音色
                -content:文本内容
              或
              -序号(按先后顺序排列)
               -type:"环境声"
               -info(详细信息):使用英文描述
              对于"voice_type"的选择，根据"speaker"和"content"的内容，从音色列表中选择合适的音色。
              文本内容如下：{text_content}
              音色列表如下：{voice_list}
              最终结果严格按照JSON格式输出，示例如下：
              {{
                "1": {{
                  "type": "人声",
                  "info": {{
                    "speaker": "旁白",
                    "style": "东方浩然",
                    "voice_type": "zh_male_dongfanghaoran_moon_bigtts",
                    "content": "但有一年的秋季，大约是得到祥林嫂好运的消息之后的又过了两个新年，她竟又站在四叔家的堂前了。"
                  }}
                }},
                "2": {{
                  "type": "人声",
                  "info": {{
                    "speaker": "旁白",
                    "style": "东方浩然",
                    "voice_type": "zh_male_dongfanghaoran_moon_bigtts",
                    "content": "四婶起刻还踌躇，待到听完她自己的话，眼圈就有些红了。"
                  }}
                }}
              }}
             """

    #定义提示词（如果环境声生成的结果不行，可以使用第二个提示词，去掉环境音，只生成角色对话和旁白）
    prompt2 = f"""
            请根据文本的内容，按照从前往后的顺序依次进行分析，分类为旁白或角色的对话。请逐行分析，不要遗漏内容。并严格按照给定的JSON格式进行输出。
            如果当前的内容中不存在对话，也就是没有中文的“”或者【】存在，表明当前内容属于旁白。
            如果当前的内容中存在对话，那么根据上下文寻找说话的角色，并根据上下文判断此时角色的情感。角色说的内容，就是“”或【】中包裹的内容。
            划分的示例如下：
            例句：但有一年的秋季，大约是得到祥林嫂好运的消息之后的又过了两个新年，她竟又站在四叔家的堂前了。
            划分：当前句子没有对话，属于旁白，整个句子属于旁白的内容。
            例句：“祥林嫂，你放着罢!我来摆。”四婶慌忙的说。
            划分：当前句子出现对话，通过上下文寻找说话角色"speaker"为：四婶；对话内容"content"为“”或【】包裹住的内容。
            结果使用JSON的格式进行回答。
            JSON格式应包含两个主要部分："type"（统一都是人声）和 "info"(对于人声的详细描述)。
            "info"中的内容包括"speaker"(该声音的说话人，如果没有明确的说话人，就是旁白),"style"(风格和语气),"voice_type"和"content"(这段话的内容)。
            具体形式如下：
            -序号(按先后顺序排列)
              -type:"人声"
              -info(详细信息):
                -speaker:人物角色或旁白
                -style:风格
                -voice_type:音色
                -content:文本内容
            对于"voice_type"的选择，根据当前的文本内容对应的"speaker"和"content"选择音色列表中合适的音色。
            文本内容如下：{file_content}
            音色列表如下：{voice_list}
            请严格按照给定的JSON格式进行输出，示例如下：
            {{
                "1": {{
                  "type": "人声",
                  "info": {{
                    "speaker": "旁白",
                    "style": "渊博小叔",
                    "voice_type": "zh_male_yuanboxiaoshu_moon_bigtts",
                    "content": "但有一年的秋季，大约是得到祥林嫂好运的消息之后的又过了两个新年，她竟又站在四叔家的堂前了。"
                  }}
                }},
                "2": {{
                  "type": "人声",
                  "info": {{
                    "speaker": "旁白",
                    "style": "渊博小叔",
                    "voice_type": "zh_male_yuanboxiaoshu_moon_bigtts",
                    "content": "四婶起刻还踌躇，待到听完她自己的话，眼圈就有些红了。"
                  }}
                }},
            }}
            """

    #接受gpt-4o的输出回答
    resp = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "你是一个精通于分析文本内容的专家。根据下面用户提供的文本执行相应的任务"},
            {"role": "user", "content": prompt1},
        ]
    )
    # print(resp)
    # print(resp.choices[0].message.content)
    return resp.choices[0].message.content


# output_file 将gpt-4o的输出结果使用json文件存储，存放的文件夹为output
def output_file(json_data, write_path):
    """
    将模型的回答写到json文件中
    """
    #使用正则表达式去除大模型输出结果前面和后面多余的内容
    cleaned_content = re.sub(r'^```json\s*', '', json_data).strip()
    cleaned_output = re.sub(r'```\s*$', '', cleaned_content)
    #去掉转移字符
    cleaned_json_str = cleaned_output.replace('\\', '')
    # print(cleaned_json_str)
    # print("测试分割线-----------")
    with open(write_path, 'w', encoding='utf-8') as file:
        file.write(cleaned_json_str)

# 完整的处理流程
def transform_to_json(file_path):
    """
        file_path:要提供给gpt-4o模型的文本在的文件夹路径
        write_path:存放处理后json文件的文件夹路径
        通过gpt-4o模型，对文件夹中的全部内容进行处理，按照指定的json格式输出json文件
        """
    for filename in os.listdir(file_path):
        if filename.endswith('.txt'):
            read_path = os.path.join(file_path, filename)
            write_path = os.path.join(file_path, filename.replace('.json', '.txt'))

            # 读取文本内容
            with open(read_path, 'r', encoding='utf-8') as input_file:
                content = input_file.read()
            #获取gpt-4o的输出结果
            data = chat_completions(content, voice_list)
            # 将处理后内容写入json文件中
            output_file(data, write_path)

if __name__ == '__main__':

    # deal_files('./origin_text', './new_text')
    # with open("./new_text/祝福_节选.txt",'r',encoding='utf-8') as file:
    #     file_content = file.read()
    # json_data = chat_completions(file_content, voice_list)
    # output_file(json_data, './output/test3.json')
    with open("./new_text/绑定内娱嫂子系统后_第七章.txt",'r',encoding='utf-8') as file:
        file_content = file.read()
    json_data = chat_completions(file_content, voice_list)
    output_file(json_data, './output/绑定内娱嫂子系统后_第七章.json')
